package com.siao.component
{
	import com.siao.component.gif.events.FrameEvent;
	import com.siao.component.gif.player.GIFPlayer;
	import com.siao.events.BytesEvent;
	import com.siao.loader.BytesResolver;
	import com.siao.loader.BytesStream;
	
	import flash.display.Bitmap;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	[Event(name="cache", type="com.siao.events.BytesEvent")]
	
	[Event(name="complete", type="com.siao.events.BytesEvent")]
	
	[Event(name="error", type="com.siao.events.BytesEvent")]
	
	[Event(name="progress", type="flash.events.ProgressEvent")]
	
	/**
	 * 字节位图
	 * @author SiaoLeon
	 */
	public class BytesBitmap extends Bitmap
	{
		// -------------------------------------------------------------------------------------------------------- 静态常量
		
		// -------------------------------------------------------------------------------------------------------- 静态变量
		
		// -------------------------------------------------------------------------------------------------------- 静态方法
		
		// -------------------------------------------------------------------------------------------------------- 静态函数
		
		// -------------------------------------------------------------------------------------------------------- 属性
		
		private var _width:Number;
		
		override public function set width(value:Number):void
		{
			this._width = value;
			this.resize();
		}
		
		private var _height:Number;
		
		override public function set height(value:Number):void
		{
			this._height = value;
			this.resize();
		}
		
		private var _progressive:Boolean;
		
		/**
		 * 是否开启渐进式加载
		 * @return
		 */
		public function get progressive():Boolean
		{
			return this._progressive;
		}
		
		public function set progressive(value:Boolean):void
		{
			this._progressive = value;
		}
		
		private var _url:String;
		
		/**
		 * 位图加载地址
		 * @return
		 */
		public function get url():String
		{
			return this._url;
		}
		
		public function set url(value:String):void
		{
			if (this._url == value && value != null && value != "")
			{
				return;
			}
			
			this._url = value;
			this.bitmapData = null;
			
			if (this.stream.connected)
			{
				this.stream.close();
			}
			
			if (this.url != null)
			{
				if (this.gif != null)
				{
					this.gif.stop();
					this.gif = null;
				}
				this.registerStreamEventListener();
				this.stream.load(new URLRequest(this.url));
			}
		}
		
		// -------------------------------------------------------------------------------------------------------- 变量
		
		private var stream:BytesStream;
		
		private var resolver:BytesResolver;
		
		private var gif:GIFPlayer;
		
		// -------------------------------------------------------------------------------------------------------- 构造
		
		/**
		 * 构造函数
		 * @param url 加载地址，设定后构造时立刻开始加载位图
		 * @param progressive 是否开启渐进式加载显示
		 */
		public function BytesBitmap(url:String=null, progressive=false)
		{
			this.stream = new BytesStream();
			this.resolver = new BytesResolver();
			this.progressive = progressive;
			this.url = url;
			
			this.resolver.addEventListener(BytesEvent.COMPLETE, onResolverComplete, false, 0, true);
			this.resolver.addEventListener(BytesEvent.ERROR, onError, false, 0, true);
			
			this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
		}
		
		// -------------------------------------------------------------------------------------------------------- 方法
		
		/**
		 * 加载二进制数据
		 * @param bytes
		 */
		public function loadBytes(bytes:ByteArray):void
		{
			this.resolver.parser(bytes, !this.stream.connected);
		}
		
		// -------------------------------------------------------------------------------------------------------- 函数
		
		/**
		 * 定义尺寸
		 */
		protected function resize():void
		{
			if (!isNaN(this._width) && this.width > 0)
			{
				super.width = this._width;
			}
			
			if (!isNaN(this._height) && this.height > 0)
			{
				super.height = this._height;
			}
		}
		
		/**
		 * 添加到舞台时
		 * @param event
		 */
		private function onAddedToStage(event:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage, false, 0, true);
			
			if (this.gif != null)
			{
				this.gif.play();
			}
		}
		
		/**
		 * 从舞台移除时
		 * @param event
		 */
		private function onRemovedFromStage(event:Event):void
		{
			this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
			this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
			
			if (this.gif != null)
			{
				this.gif.stop();
			}
		}
		
		/**
		 * 保存数据
		 */
		private function save():void
		{
			if (this.stream.data == null)
			{
				return;
			}
			
			this.loadBytes(this.stream.data);
		}
		
		/**
		 * 注册二进制加载流的事件侦听
		 */
		private function registerStreamEventListener():void
		{
			this.stream.addEventListener(ProgressEvent.PROGRESS, onProgress, false, 0, true);
			this.stream.addEventListener(BytesEvent.COMPLETE, onComplete, false, 0, true);
			this.stream.addEventListener(BytesEvent.ERROR, onError, false, 0, true);
		}
		
		/**
		 * 移除二进制加载流的事件侦听
		 */
		private function removeStreamEventListener():void
		{
			this.stream.removeEventListener(ProgressEvent.PROGRESS, onProgress);
			this.stream.removeEventListener(BytesEvent.COMPLETE, onComplete);
			this.stream.removeEventListener(BytesEvent.ERROR, onError);
		}
		
		/**
		 * 二进制加载流进度时
		 * @param event
		 */
		private function onProgress(event:ProgressEvent):void
		{
			if (this.progressive)
			{
				this.save();
			}
			this.dispatchEvent(event);
		}
		
		/**
		 * 二进制加载流完成时
		 * @param event
		 */
		private function onComplete(event:BytesEvent):void
		{
			this.removeStreamEventListener();
			this.stream.close();
			this.save();
		}
		
		/**
		 * 解析二进制数据完成时
		 * @param event
		 */
		private function onResolverComplete(event:Event):void
		{
			if (this.resolver.content is GIFPlayer)
			{
				this.gif = this.resolver.content;
				this.gif.addEventListener(FrameEvent.FRAME_RENDERED, onGIFEnterFrame, false, 0, true);
				
				if (this.stage == null)
				{
					this.gif.stop();
				}
				else
				{
					this.gif.play();
				}
			}
			
			if (!(this.resolver.content is Bitmap))
			{
				this.dispatchEvent(new BytesEvent(BytesEvent.ERROR));
				return;
			}
			
			if (this.bitmapData != null)
			{
				this.bitmapData.dispose();
			}
			
			this.bitmapData = (this.resolver.content as Bitmap).bitmapData;
			this.resize();
			this.dispatchEvent(new BytesEvent((this.stream.connected) ? BytesEvent.CACHE : BytesEvent.COMPLETE));
		}
		
		/**
		 * 加载或解析错误时
		 * @param event
		 */
		private function onError(event:BytesEvent):void
		{
			this.removeStreamEventListener();
			this.stream.close();
			this.dispatchEvent(new BytesEvent(BytesEvent.ERROR));
		}
		
		/**
		 * GIF帧动画播放时
		 * @param event
		 */
		private function onGIFEnterFrame(event:Event):void
		{
			this.bitmapData = (event.target as GIFPlayer).bitmapData;
			this.resize();
		}
	
	}
}
